package com.zh.javafeaturesupport;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.zh.javafeaturesupport.bean.Student;
import com.zh.javafeaturesupport.databinding.ActivityMainBinding;
import com.zh.javafeaturesupport.util.StreamExtTest;
import com.zh.javafeaturesupport.util.TempFileDownloader;

import java.io.File;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

import io.github.burukeyou.dataframe.iframe.SDFrame;
import io.github.burukeyou.dataframe.iframe.item.FI2;
import java9.util.J8Arrays;
import java9.util.Lists;
import java9.util.Optional;
import java9.util.concurrent.CompletableFuture;
import java9.util.stream.Collectors;
import java9.util.stream.Stream;
import java9.util.stream.StreamSupport;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    private ActivityMainBinding binding;

    @SuppressLint("SetTextI18n")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        String streamResult = testStream();
        String parallelStreamResult = testParallelStream();
        String optionalResult = testOptional();
        String completableFutureResult = testCompletableFuture();

        binding.resultText.setText(
                streamResult + "\n" + parallelStreamResult + "\n" + optionalResult + "\n" + completableFutureResult
        );

        testDownloadFile()
                .exceptionally((e) -> {
                    log("下载文件失败: " + e.getMessage());
                    return Lists.of();
                }).thenAccept(downloadFileList -> {
                    runOnUiThread(() -> {
                        if (downloadFileList == null || downloadFileList.isEmpty()) {
                            return;
                        }
                        List<String> filePath = StreamSupport.stream(downloadFileList)
                                .map((File::getAbsolutePath))
                                .toList();
                        String downloadResult = StreamSupport.stream(filePath).collect(Collectors.joining("\n"));
                        log("下载文件成功: " + downloadResult);
                        binding.resultText.setText(
                                binding.resultText.getText() + "\n下载文件成功: " + downloadResult
                        );
                    });
                });

        testJDFrame();

        testSteamExt();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        binding = null;
    }

    private String testStream() {
        // 数组使用Stream
        int[] array = {1, 2, 3, 4, 5, 6, 7, 8};
        int result = J8Arrays.stream(array)
                .filter((item) -> {
                    return item == 1;
                })
                // 找到id为1的元素
                .findFirst()
                // 没有找到，则返回-1
                .orElse(-1);

        // List使用Stream
        List<Integer> list = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).collect(Collectors.toList());
        return StreamSupport.stream(list)
                // 过滤，只取偶数
                .filter((item) -> {
                    return item % 2 == 0;
                })
                // 转换为Double
                .mapToDouble(Double::valueOf)
                // 转换为String
                .mapToObj(String::valueOf)
                // 逗号分割为字符串
                .collect(Collectors.joining(", "));
    }

    private String testParallelStream() {
        return Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
                // 并行流
                .parallel()
                // 过滤，只取偶数
                .filter(item -> item % 2 == 0)
                // 转换为字符串
                .map(String::valueOf)
                // 收集结果
                .collect(Collectors.joining(", "));
    }

    private CompletableFuture<List<File>> testDownloadFile() {
        List<String> urls = Arrays.asList(
                "https://www.baidu.com",
                "https://www.qq.com",
                "https://www.sina.com"
        );

        // 创建异步任务
        List<CompletableFuture<File>> futures = StreamSupport
                .stream(urls)
                // 使用CompletableFuture下载文件
                .map(url -> CompletableFuture.supplyAsync(() -> {
                    return TempFileDownloader.downloadTempFile(getApplicationContext(), url, ".html");
                }))
                .collect(Collectors.toList());

        // 批量提交任务
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[]{}));
        return allFutures.thenApply(v ->
                StreamSupport.stream(futures)
                        .map(CompletableFuture::join)
                        .collect(Collectors.toList())
        );
    }

    private String testOptional() {
        return Optional
                // 创建Optional
                .<String>ofNullable(null)
                // 默认值
                .orElse("default value");
    }

    private String testCompletableFuture() {
        // 无返回值的任务
        CompletableFuture.runAsync(() -> {
            log("任务1执行中...");
        }).join();

        // 有返回值的任务
        String result = CompletableFuture.supplyAsync(() -> "Hello")
                .thenApply(value -> value + " Completable Future")
                // 转小写
                .thenApply(String::toLowerCase)
                // 错误处理
                .exceptionally(e -> "Error: " + e.getMessage())
                // 等待结果
                .join();
        log("任务2的执行结果: " + result);

        // 合并2个任务
        CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {
            return "Hello";
        });
        CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> {
            return "Completable Future";
        });
        return task1.thenCombine(task2, (result1, result2) -> {
            return result1 + " " + result2;
        }).join();
    }

    /**
     * JDFrame
     * 文档：<a href="https://burukeyou.github.io/JDFrame/#/pages/guide/quick-start">...</a>
     */
    private void testJDFrame() {
        List<Student> studentList = Arrays.asList(
                new Student(1, "张三", "一中", "一年级", 11, new BigDecimal("80")),
                new Student(2, "李四", "一中", "二年级", 12, new BigDecimal("90")),
                // 年龄为null
                new Student(3, "王五", "二中", "一年级", null, new BigDecimal("70")),
                new Student(4, "赵六", "二中", "三年级", 15, new BigDecimal("85")),
                new Student(5, "钱七", "三中", "二年级", 14, new BigDecimal("95"))
        );

        // 筛选出分数≥60且年级为"一年级"或"二年级"的学生，然后按学校分组计算总分，取总分最高的前5所学校
        List<FI2<String, BigDecimal>> lists = SDFrame.read(studentList)
                // 筛选出分数≥60
                .whereGe(Student::getScore, new BigDecimal("60"))
                // 限定年级为"一年级"或"二年级"
                .whereIn(Student::getLevel, Arrays.asList("一年级", "二年级"))
                // 按学校分组，计算总分
                .groupBySum(Student::getSchool, Student::getScore)
                // 倒序
                .sortDesc(FI2::getC2)
                // 取前5个
                .cutFirst(5)
                // 聚合结果
                .toLists();

        for (FI2<String, BigDecimal> item : lists) {
            // 学校名称
            String school = item.getC1();
            // 总分
            BigDecimal totalScore = item.getC2();
            log(school + ": " + totalScore);
        }
    }

    /**
     * 测试SteamExt拓展
     */
    private void testSteamExt() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        StreamExtTest.testForEach(list, new Function1<Integer, Unit>() {
            @Override
            public Unit invoke(Integer item) {
                log("StreamExt forEach item: " + item);
                return null;
            }
        });
    }

    private void log(String message) {
        Log.d(TAG, message);
    }
}